package com.hps.demo.discovery;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.I0Itec.zkclient.ZkClient;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @author heps
 * @since 2020/8/15
 */
@Slf4j
@Component
public class ServiceDiscovery implements InitializingBean {

    @Value("${registry.address}")
    private String registryAddress;

    private ConnectManage connectManage;

    /**
     * 服务地址列表
     */
    private volatile List<String> addressList = new ArrayList<>();

    private static final String ZK_REGISTRY_PATH = "/rpc";

    private ZkClient client;

    public ServiceDiscovery(ConnectManage connectManage) {
        this.connectManage = connectManage;
    }

    private ZkClient connectServer() {
        return new ZkClient(registryAddress, 20000, 20000);
    }

    private void watchNode(ZkClient client) {
        List<String> nodeList = client.subscribeChildChanges(ZK_REGISTRY_PATH, (s, nodes) -> {
            log.info("监听到子节点数据变化{}", JSON.toJSONString(nodes));
            addressList.clear();
            getNodeData(nodes);
            updateConnectedServer();
        });
        getNodeData(nodeList);
        log.info("已发现服务列表...{}", JSON.toJSONString(addressList));
        updateConnectedServer();
    }

    private void updateConnectedServer() {
        connectManage.updateConnectedServer(addressList);
    }

    private void getNodeData(List<String> nodes) {
        log.info("/rpc子节点数据为: {}", JSON.toJSONString(nodes));
        for (String node : nodes) {
            String address = client.readData(ZK_REGISTRY_PATH + "/" + node);
            addressList.add(address);
        }
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        client = connectServer();
        watchNode(client);
    }
}
